/*
 * accountstore.cpp - accounts storage class
 * Copyright (C) 2009  Sergei Stolyarov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * Kajim::ChatInputText widget implements basic functions required
 * by chat text entry widget: history navigation, autocompletion etc
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QtCore>
#include <QtDebug>

#include "accountstore.h"
#include "settings.h"
#include "constants.h"
#include "account.h"

namespace Kajim
{

struct AccountStore::Private
{
    QHash<int, Account*> accounts;
};

AccountStore::AccountStore(QObject *parent)
    :QObject(parent)
{
    d = new Private;

    QStringList accounts_list = Kajim::Settings::get("accounts/list").toStringList();
    QStringList params;
    params << "jid" << "password" << "save_password" << "resource" << "host" << "port" << "use_host";
    Kajim::Account * account;

    Q_FOREACH (const QString & acc, accounts_list) {
        QString key = Kajim::Settings::ACCOUNT_PARAM_KEY_TEMPLATE.arg(acc);
        account = new Kajim::Account();
        account->setParam("name", acc);

        Q_FOREACH(const QString & param_name, params) {
            account->setParam(param_name, Kajim::Settings::get(key + param_name).toString());
        }
        d->accounts.insert(Common::allocateHandler(), account);
    }

}

AccountStore * AccountStore::instance()
{
    if (AccountStore::inst == 0) {
        AccountStore::inst = new AccountStore();
    }


    return AccountStore::inst;
}

AccountStore::~AccountStore()
{
    delete d;
}

QStringList AccountStore::accountNames()
{
    QStringList keys;
    Q_FOREACH (const Account * account, d->accounts) {
        keys.append(account->param("name"));
    }
    return keys;
}

QList<int> AccountStore::accountsList()
{
    return d->accounts.uniqueKeys();
}

Account * AccountStore::accountByName(const QString & name)
{
    Account * found = 0;

    Q_FOREACH(Account * account, d->accounts) {
        if (account->param("name") == name) {
            found = account;
            break;
        }
    }

    return found;
}

Account * AccountStore::account(const int handler)
{
    if (!d->accounts.contains(handler)) {
        return 0;
    }

    return d->accounts[handler];
}

int AccountStore::addAccount(Account * account)
{
    if (accountByName(account->param("name")) != 0) {
        // account with the same name already exists, for example
        return Kajim::Common::HandlerInvalid;
    }

    int h = Common::allocateHandler();
    d->accounts.insert(h, account);
    emit AccountAdded(h);
    return h;
}

bool AccountStore::updateAccount(Account * account, Account * newAccount)
{
    QList<int> keys = d->accounts.keys(account);
    if (keys.count() == 0) {
        return false;
    }

    return updateAccount(keys.first(), newAccount);

}

bool AccountStore::updateAccount(int h, Account * newAccount)
{
    Account * account = d->accounts[h];

    QStringList params;
    QString oldName = account->param("name");

    params << "name" << "jid" << "password" << "save_password" << "resource" << "host" << "port" << "use_host";

    bool updated = false;

    Q_FOREACH(const QString & param, params) {
        QString newValue=newAccount->param(param);
        if (account->param(param) != newValue) {
            account->setParam(param, newValue);
            updated = true;
        }
    }

    if (updated) {
        emit AccountUpdated(h);
        return true;
    }
    return false;

}


void AccountStore::removeAccount(Account * account)
{
    // remove from the config
    QString key = Kajim::Settings::ACCOUNT_PARAM_KEY_TEMPLATE.arg(account->param("name"));
    Kajim::Settings::remove(key);

    // remove from the list
    QList<int> keys = d->accounts.keys(account);
    int h = Kajim::Common::HandlerInvalid;
    Q_FOREACH(int key, keys) {
        d->accounts.remove(key);
        h = key;
        break;
    }

    if (h == Common::HandlerInvalid) {
        return;
    }
    QString accountName = account->param("name");
    delete account;
    emit AccountRemoved(h);
}

void AccountStore::removeAccount(int h)
{
    if (!d->accounts.contains(h)) {
        return;
    }
    Account * account = d->accounts[h];
    QString key = Kajim::Settings::ACCOUNT_PARAM_KEY_TEMPLATE.arg(account->param("name"));
    Kajim::Settings::remove(key);
    d->accounts.remove(h);
    QString accountName = account->param("name");
    delete account;
    emit AccountRemoved(h);
}


void AccountStore::sync()
{
    QStringList params;
    params << "jid" << "password" << "save_password" << "resource" << "host" << "port" << "use_host";

    Q_FOREACH (Kajim::Account* account, d->accounts) {
        QString name = account->param("name");

        QString key = Kajim::Settings::ACCOUNT_PARAM_KEY_TEMPLATE.arg(name);
        Q_FOREACH (const QString & paramName, params) {
            Kajim::Settings::set(key + paramName, account->param(paramName));
        }
    }
    Kajim::Settings::set("accounts/list", accountNames());
}

AccountStore * AccountStore::inst = 0;

}
